import 'dart:async';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class BaseRouterUtil extends NavigatorObserver {
  /// 配置路由
  static Map<String, WidgetBuilder> _configRoutes = {};

  Map<String, WidgetBuilder> get configRoutes => _configRoutes;

  void setConfigRoutes(Map<String, WidgetBuilder> value) {
    _configRoutes = value;
  }

  /// 当前路由栈
  static List<Route> _mRoutes;

  /// 获取当前的路由栈
  List<Route> get routes => _mRoutes;

  /// 获取当前最外层的路由
  Route get currentRoute => _mRoutes[_mRoutes.length - 1];

  /// 监听器来监听路由跳转
  // ignore: close_sinks
  static StreamController _streamController;

  /// 获取当前路由的监听器
  StreamController get streamController => _streamController;

  /// 用来做路由跳转
  static NavigatorState _navigator;

  /// 当前的单例对象
  static BaseRouterUtil _baseRouterUtil;

  /// 获取当前路由对象的实例
  static BaseRouterUtil getInstance() {
    if (_baseRouterUtil == null) {
      _baseRouterUtil = new BaseRouterUtil();
      _streamController = StreamController.broadcast();
    }
    return _baseRouterUtil;
  }

  // 原生 push 页面
  Future push<T>(Widget widget, {RouteSettings settings}) {
    if (settings != null) return _navigator.push<T>(CupertinoPageRoute(builder: (context) => widget, settings: settings));
    return _navigator.push<T>(CupertinoPageRoute(builder: (context) => widget));
  }

  // 原生 pushReplacement 页面 可以将新的页面替换掉旧的页面，旧的页面被销毁；
  Future pushReplacement<T>(Widget widget) {
    return _navigator.pushReplacement(CupertinoPageRoute(builder: (context) => widget));
  }

  // 原生 pushAndRemoveUntil 页面
  Future pushAndRemoveUntil<T>(Widget widget, RoutePredicate routePredicate) {
    return _navigator.pushAndRemoveUntil(CupertinoPageRoute(builder: (context) => widget), routePredicate);
  }

  // replace 页面
  Future pushReplacementNamed(String routeName, {dynamic arguments, WidgetBuilder builder}) {
    return _navigator.pushReplacement(
      CupertinoPageRoute(builder: builder ?? configRoutes[routeName], settings: RouteSettings(name: routeName, arguments: arguments)),
    );
  }

  // push 页面
  Future pushNamed(String routeName, {dynamic arguments, WidgetBuilder builder}) {
    if (routeName != null && routeName.length > 0 && !configRoutes.containsKey(routeName)) {
      print('路由配置中 不包含此路由: $routeName');
      return Future.delayed(Duration.zero);
    }
    return _navigator.push(CupertinoPageRoute(builder: builder ?? configRoutes[routeName], settings: RouteSettings(name: routeName, arguments: arguments)));
  }

  // push一个页面， 移除该页面下面所有页面
  pushNamedAndRemoveUntil(String newRouteName, {RoutePredicate routePredicate, dynamic arguments}) {
    if (routePredicate != null) return _navigator.pushNamedAndRemoveUntil(newRouteName, routePredicate, arguments: arguments);
    return _navigator.pushNamedAndRemoveUntil(newRouteName, (Route<dynamic> route) => false, arguments: arguments);
  }

  // pop当前页面， 并push下一个界面
  popAndPushNamed(String newRouteName, {dynamic result, dynamic arguments}) {
    return _navigator.popAndPushNamed(newRouteName, result: result, arguments: arguments);
  }

  // 获取路由数据
  static getArguments(BuildContext context) {
    return ModalRoute.of(context).settings.arguments;
  }

  // pop 页面
  pop<T extends Object>([T result]) {
    _navigator.pop(result);
  }

  // 一直退出直到某一个页面
  popUntil(RoutePredicate routePredicate) {
    _navigator.popUntil(routePredicate);
  }

  // 当调用Navigator.push时回调
  @override
  void didPush(Route route, Route previousRoute) {
    super.didPush(route, previousRoute);
    if (_mRoutes == null) {
      _mRoutes = <Route>[];
    }
    // 这里过滤调push的是dialog的情况
    if (route is CupertinoPageRoute || route is MaterialPageRoute) {
      _mRoutes.add(route);
      routeObserver();
    }
  }

  // 当调用Navigator.replace时回调
  @override
  void didReplace({Route newRoute, Route oldRoute}) {
    super.didReplace();
    if (newRoute is CupertinoPageRoute || newRoute is MaterialPageRoute) {
      _mRoutes.remove(oldRoute);
      _mRoutes.add(newRoute);
      routeObserver();
    }
  }

  // 当调用Navigator.pop时回调
  @override
  void didPop(Route route, Route previousRoute) {
    super.didPop(route, previousRoute);
    if (route is CupertinoPageRoute || route is MaterialPageRoute) {
      _mRoutes.remove(route);
      routeObserver();
    }
  }

  @override
  void didRemove(Route removedRoute, Route oldRoute) {
    super.didRemove(removedRoute, oldRoute);
    if (removedRoute is CupertinoPageRoute || removedRoute is MaterialPageRoute) {
      _mRoutes.remove(removedRoute);
      routeObserver();
    }
  }

  void routeObserver() {
    // 当前页面的navigator，用来路由跳转
    _navigator = _mRoutes[_mRoutes.length - 1].navigator;
    streamController.sink.add(_mRoutes);
  }
}
